/**
 * 嫌疑人身份聚合服务
 * 从各类数据中提取人员信息并建立"人-账号"映射关系
 */

export class SubjectService {
    /**
     * 从案件数据中提取所有人员及其关联账号
     * @param {string} caseId 案件ID
     * @returns {Promise<Array>} 人员列表
     */
    static async extractSubjects(caseId) {
        if (!caseId) {
            throw new Error('案件ID不能为空');
        }

        try {
            // 1. 从银行流水中提取人员和银行卡号
            const bankSubjects = await this.extractFromBankTransactions(caseId);

            // 2. 从通话记录中提取人员和手机号
            const commSubjects = await this.extractFromCallRecords(caseId);

            // 3. 从人员信息表中提取人员 (新增)
            const personSubjects = await this.extractFromPersonnel(caseId);

            // 4. 合并去重
            const mergedSubjects = this.mergeSubjects(bankSubjects, commSubjects, personSubjects);

            console.log(`[SubjectService] 从案件 ${caseId} 中提取到 ${mergedSubjects.length} 个人员`);
            return mergedSubjects;
        } catch (error) {
            console.error('[SubjectService] 提取人员失败:', error);
            throw error;
        }
    }

    /**
     * 从银行流水中提取人员和账号
     * 注：只提取账号持有人，不包含交易对手方（避免下拉框内容过多）
     */
    static async extractFromBankTransactions(caseId) {
        const sql = `
            SELECT DISTINCT
                customer_name as name,
                NULL as id_card,
                card_number as account_number
            FROM bank_transactions
            WHERE case_id = ?
                AND (
                    (customer_name IS NOT NULL AND customer_name != '')
                    OR (card_number IS NOT NULL AND card_number != '')
                )
            ORDER BY customer_name
        `;

        if (!window.electronAPI) return [];

        const result = await window.electronAPI.data.query({
            caseId,
            sql,
            params: [caseId]
        });

        if (!result.success) {
            console.warn('[SubjectService] 银行流水查询失败:', result.message);
            return [];
        }

        // 按姓名+身份证聚合
        const subjectMap = new Map();

        result.data.forEach(row => {
            const rawName = row.name || '';
            const rawCard = row.account_number || '';

            // If both missing, skip
            if (!rawName && !rawCard) return;

            const displayName = rawName || `未知户名 (${rawCard.slice(-6)})`;
            // If name is present, key by name_id. If name missing, key by card.
            const key = rawName ? `${rawName}_${row.id_card || 'unknown'}` : `unknown_card_${rawCard}`;

            if (!subjectMap.has(key)) {
                subjectMap.set(key, {
                    id: this.generateSubjectId(displayName, row.id_card || rawCard),
                    name: displayName,
                    idCard: row.id_card || null,
                    accounts: {
                        bank: [],
                        phone: [],
                        vehicle: []
                    },
                    dataSource: ['bank']
                });
            }

            const subject = subjectMap.get(key);
            if (rawCard && !subject.accounts.bank.includes(rawCard)) {
                subject.accounts.bank.push(rawCard);
            }
        });

        return Array.from(subjectMap.values());
    }

    /**
     * 从通话记录中提取人员和手机号
     */
    static async extractFromCallRecords(caseId) {
        const sql = `
            SELECT DISTINCT
                user_name as name,
                user_number as phone
            FROM call_records
            WHERE case_id = ?
                AND user_name IS NOT NULL
                AND user_name != ''
            ORDER BY user_name
        `;

        if (!window.electronAPI) return [];

        const result = await window.electronAPI.data.query({
            caseId,
            sql,
            params: [caseId]
        });

        if (!result.success) {
            console.warn('[SubjectService] 通话记录查询失败:', result.message);
            return [];
        }

        // 按姓名聚合（通话记录通常没有身份证）
        const subjectMap = new Map();

        result.data.forEach(row => {
            const key = row.name; // 仅用姓名作为key

            if (!subjectMap.has(key)) {
                subjectMap.set(key, {
                    id: this.generateSubjectId(row.name, null),
                    name: row.name,
                    idCard: null,
                    accounts: {
                        bank: [],
                        phone: [],
                        vehicle: []
                    },
                    dataSource: ['call']
                });
            }

            const subject = subjectMap.get(key);
            if (row.phone && !subject.accounts.phone.includes(row.phone)) {
                subject.accounts.phone.push(row.phone);
            }
        });

        return Array.from(subjectMap.values());
    }

    /**
     * 从人员信息表(personal_info)中提取人员
     */
    static async extractFromPersonnel(caseId) {
        const sql = `
            SELECT 
                name, 
                id_card, 
                phone, 
                extra_data 
            FROM personal_info 
            ORDER BY name
        `;

        if (!window.electronAPI) return [];

        const result = await window.electronAPI.data.query({
            caseId,
            sql,
            params: []
        });

        if (!result.success) {
            return [];
        }

        const subjects = [];
        result.data.forEach(row => {
            if (!row.name) return;

            subjects.push({
                id: this.generateSubjectId(row.name, row.id_card),
                name: row.name,
                idCard: row.id_card || null,
                accounts: {
                    bank: [],
                    phone: row.phone ? [row.phone] : [],
                    vehicle: []
                },
                dataSource: ['personnel']
            });
        });
        return subjects;
    }

    /**
     * 合并不同来源的人员信息
     */
    static mergeSubjects(bankSubjects, commSubjects, personSubjects = []) {
        const mergedMap = new Map();

        // Helper to merge
        const mergeInto = (target, source) => {
            target.dataSource = [...new Set([...target.dataSource, ...source.dataSource])];

            // Merge phones
            source.accounts.phone.forEach(p => {
                if (!target.accounts.phone.includes(p)) target.accounts.phone.push(p);
            });

            // Merge banks
            source.accounts.bank.forEach(b => {
                if (!target.accounts.bank.includes(b)) target.accounts.bank.push(b);
            });

            // Update ID card if missing
            if (!target.idCard && source.idCard) {
                target.idCard = source.idCard;
            }
        };

        // 1. Bank Subjects
        bankSubjects.forEach(s => mergedMap.set(s.name, s));

        // 2. Comm Subjects
        commSubjects.forEach(s => {
            if (mergedMap.has(s.name)) {
                mergeInto(mergedMap.get(s.name), s);
            } else {
                mergedMap.set(s.name, s);
            }
        });

        // 3. Personnel Subjects
        personSubjects.forEach(s => {
            if (mergedMap.has(s.name)) {
                mergeInto(mergedMap.get(s.name), s);
            } else {
                mergedMap.set(s.name, s);
            }
        });

        return Array.from(mergedMap.values());
    }

    /**
     * 生成人员唯一ID
     */
    static generateSubjectId(name, idCard) {
        const base = idCard || name;
        return `subject_${this.hashCode(base)}`;
    }

    /**
     * 简单哈希函数
     */
    static hashCode(str) {
        let hash = 0;
        for (let i = 0; i < str.length; i++) {
            const char = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & hash; // Convert to 32bit integer
        }
        return Math.abs(hash).toString(36);
    }

    static _cache = new Map();

    static async extractSubjectsWithCache(caseId) {
        if (this._cache.has(caseId)) {
            return this._cache.get(caseId);
        }

        const subjects = await this.extractSubjects(caseId);
        this._cache.set(caseId, subjects);
        return subjects;
    }

    static clearCache(caseId = null) {
        if (caseId) {
            this._cache.delete(caseId);
        } else {
            this._cache.clear();
        }
    }
}
